
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <errno.h>
#include <sys/reboot.h>

//#include "mk_util.h"
#include "plcgw_cfg.h"
#include "ota_server.h"




/*****************************************************************/
const char fw_ver[]="otaServo-v1.0.2";

/***************************************************************/
typedef struct {
	long mtype;
	char mtext[256];
}msgbuf_t;


static key_t key_msg_app2manager;  //  app --->  main manager
static int msqid_app2manager = -1;

static key_t key_msg_manager2app;  //  app <---- main manager
static int msqid_manager2app = -1;

/********************************************************************/

void system_reset()
{
#ifdef ESP32

#else
	printf("exit and reboot !.........\n");
  #if 0
	//exit(0);
	system("reboot");
  #else
	sync(); // 同步磁盘数据，将缓存数据回写到硬盘，以防数据丢失（必须）
	reboot(RB_AUTOBOOT);
  #endif	
#endif
}


int send_msg_to_app(const void *psrc, int len)
{
	if(msqid_manager2app == -1) {
		return -1;
	}

	
	int msg_buf_len = len + sizeof(long);
	msgbuf_t *pbuf = (msgbuf_t *)malloc(msg_buf_len);
	if(pbuf == NULL) {
		perror("malloc of send_plc_msg_queue\n");
		return -1;
	}

	memcpy(pbuf->mtext, psrc, len);

	int ret = 0;
	pbuf->mtype = MSG_TYPE;
	ret = msgsnd (msqid_manager2app, pbuf, len*sizeof (pbuf->mtext[0]), IPC_NOWAIT);
	if (ret == -1) {
		perror ("msgsnd");
		printf("%s()\n", __FUNCTION__);
	}

	free(pbuf);
	return 0;
}

int send_strcmd_to_app(const char *pcmd, const void *pdata)
{
	if(msqid_manager2app == -1) {
		printf("msqid_app2manager not exist\n");
		return -1;
	}

	unsigned int cmd_len = strlen(pcmd);
	unsigned int data_len = strlen(pdata);
	unsigned int total_msglen = cmd_len+data_len+1;
	unsigned int msg_buf_len = total_msglen + sizeof(long)+1;
	msgbuf_t *pbuf = (msgbuf_t *)malloc(msg_buf_len);
	if(pbuf == NULL) {
		perror("malloc of send_plc_msg_queue\n");
		return -1;
	}

	memcpy(pbuf->mtext, pcmd, cmd_len);
	pbuf->mtext[cmd_len] = 0x20;
	memcpy(&pbuf->mtext[cmd_len+1], pdata, data_len);
	pbuf->mtext[cmd_len+2] = 0;

	printf("send msg: %s\n", pbuf->mtext);

	int ret = 0;
	pbuf->mtype = MSG_TYPE;
	ret = msgsnd (msqid_manager2app, pbuf, total_msglen*sizeof (pbuf->mtext[0]), IPC_NOWAIT);
	if (ret == -1) {
		perror ("msgsnd");
		printf("%s()\n", __FUNCTION__);
	}

	free(pbuf);
	return 0;
}

/********************************************************
function: update_gw_app_pro() 把下载的文件拷贝为正确的文件名
mnt/UDISK/gw_plc/data/ota/gw/plcgw-2.2.94.bin#2.2.94  ---》 plcgw

mnt/UDISK/gw_plc/data/ota/gw/plcgw-2.4.12.tar.gz#2.4.12  ---》解压出两个文件夹与文件 
./bin/ 
./so/


文件名路径必须包括：‘/gw/’

*****************************************************/
int update_gw_app_pro(const char *filename)
{
	printf("the file: %s to update!\n", filename);
	
	const char *pt = strstr(filename, "/gw/");
	if(pt == NULL) {
		printf("Error,finename path must include: '/gw/' , now filename:%s\n", filename);
		return -1;
	}
	pt += 4;


	//send_strcmd_to_app(GW_APP_OTA_CMD, "plcgw will be update in 5 seconds.......");
	//sleep(5);
	system("./allstop.sh");
	char buf[MAX_FILENAME_LEN+100];
	
	char dst_name[MAX_FILENAME_LEN];
	int i;

	// if is tar file
	if(strstr(filename, "tar.gz")) {
		printf("is tar file\n");
		snprintf(buf, sizeof(buf)-1, "tar -zxvf %s", filename);

		printf("tar x file: %s\n", buf);
		system(buf);
		strcpy(buf, "chmod +x ./bin/*");
		system(buf);
	}
	else {
		for(i=0; i<sizeof(dst_name)-1; i++) {
			int tmp_c = pt[i];
			if(tmp_c==0 || tmp_c =='-') {
				break;
			}
			dst_name[i] = tmp_c;
		}
		dst_name[i] = 0;
		snprintf(buf, sizeof(buf)-1, "cp %s  ./bin/%s", filename, dst_name);
		

		
		printf("cp to run file: %s\n", buf);

		system(buf);

		sprintf(buf, "chmod +x ./bin/%s", dst_name);
		system(buf);

	
}

	return 0;
}

#if 0
int main(int argc, char **argv)
{
	printf("%s reset now---------\n", fw_ver);
	
	// msg to manager
	key_msg_app2manager = ftok(MSG_QUEUE_PATH, MSG_ID_TO_MANAGER);
	if(key_msg_app2manager == -1) {
		perror("ftok key_msg_app2manager");
		return -1;
	}
	msqid_app2manager = msgget(key_msg_app2manager, 0644|IPC_CREAT);
	if(msqid_app2manager == -1) {
		perror("msgget : msqid_app2manager");
		return -1;
	}


	// msg from manager
	key_msg_manager2app = ftok(MSG_QUEUE_PATH, MSG_ID_FROM_MANAGER);
	if(key_msg_manager2app == -1) {
		perror("ftok key_msg_manager2app");
		return -1;
	}
	msqid_manager2app = msgget(key_msg_manager2app, 0644|IPC_CREAT);
	if(msqid_manager2app == -1) {
		perror("msgget : msqid_manager2app");
		return -1;
	}

	printf("key_msg_app2manager=%d\n", (int)key_msg_app2manager);
	printf("key_msg_manager2app=%d\n", (int)key_msg_manager2app);

	int cnt = 0;
	while(1) {
		printf("wait msg in........................\n");
		msgbuf_t msgbuf={0};
		ssize_t msgsz = msgrcv (msqid_app2manager, &msgbuf,
			sizeof (msgbuf.mtext) - sizeof (msgbuf.mtext[0]), MSG_TYPE,
			MSG_NOERROR/* | IPC_NOWAIT*/);
		if (msgsz == -1) {
			if (errno == EIDRM) {
				printf ("msg queue(0x%08x/%d) has been killed\n", key_msg_app2manager, msqid_app2manager);
				break;
			}
			else if (errno == ENOMSG) {
				printf ("no msg now...\n");
				sleep (1);
			}
			else {
				perror ("msgrcv");
				//return -1;
				break;
			}
		}
		else {
			printf("msgType=%d, len=%lu, data:%s\n", msgbuf.mtype, msgsz,  msgbuf.mtext);
		
			if(strncmp(msgbuf.mtext, GW_APP_OTA_CMD, strlen(GW_APP_OTA_CMD)) == 0) {
				
				#if 0
				printf("update plcgw with %s now.......\n", msgbuf.mtext);
				send_msg_to_app("get it!\n", 7);
				sleep(10);
				printf("stop app now.....\n");
				system("./stop_app.sh");
				#else
				int idx = sizeof(GW_APP_OTA_CMD)+1;
				printf("update plcgw with %s now.......\n", &msgbuf.mtext[idx]);
				update_gw_app_pro(&msgbuf.mtext[idx]);
				#endif
			}
			else {
				printf("invalid manager cmd ...\n");
			}
		
			
			
		}
	}


	return 0;
}

#else
int main(int argc, char **argv)
{
	printf("%s reset now---------\n", fw_ver);

	int ret = -1;
	char file_path[MAX_FILENAME_LEN];

	sprintf(file_path, "%s%s", APP_DATA_PATH, UPDATE_FILE_NAME);
	FILE *fp = fopen(file_path, "r");
	if(fp) {
		char dat_buf[MAX_FILENAME_LEN]={0};
		int len = MAX_FILENAME_LEN;
		fgets(dat_buf, len, fp);
		fclose(fp);


		printf("update file name :%s\n", dat_buf);

		if(update_gw_app_pro(dat_buf) == 0) {
			printf("delet the file:%s\n", file_path);
			remove(file_path);
		}
		else {
			printf("update file err\n");
		}
		
	}
	else {
		printf("no update file\n");
	}
		
	return 0;
}

#endif




